# -*- coding: utf-8 -*-
"""
Created on Sat Jan 26 16:28:37 2013

@author: Winand
"""

#Shared data module
from __future__ import with_statement
import threading, cPickle as serial
from settings import SHARED_FILE_STORAGE, SHARED_NO_PERMANENT
from webapi.log import debug, error
ANSWER_OK, ANSWER_EXISTS, ANSWER_NOT_EXISTS = 1, 2, 3

sync = threading.Lock()
locks = {} #var locks
#perm = []
data = {}
if SHARED_NO_PERMANENT != True:
    try:
        with open(SHARED_FILE_STORAGE, 'rb') as f:
            data = serial.load(f) #permanent vars (stored on disk)
#            if not SHARED_NO_PERMANENT: perm = data.keys()
    except (IOError, EOFError): debug("Cannot load pickled shared data")

def __lock(name):
    if name in locks:
        locks[name].acquire()
#        print threading.currentThread().getName(), 'acquired', name, 'at', time.clock()

#TODO: switch from permanent to temp vars -- save var by default
def addVar(name, val, permanent):
    with sync:
        if name not in data:
            locks[name] = threading.Lock()
            __lock(name) #acquire lock
            data[name] = val
#            if permanent and not SHARED_NO_PERMANENT:
#                if name not in perm: #add to permanent list
#                    perm.append(name)
            return ANSWER_OK
        else: return ANSWER_EXISTS
        
def exists(name):
    with sync:
        return ANSWER_EXISTS if name in locks else ANSWER_NOT_EXISTS
            
def lock(name):
    with sync: __lock(name)

def ulock( name): #no sync!
    if name in locks:
#        print threading.currentThread().getName(), 'release', name, 'at', time.clock()
        locks[name].release()

def changed(name): #no sync!
    global any_changes
    any_changes = True
#    if name in perm:
#        try:
#            with open(SHARED_FILE_STORAGE, 'wb') as f:
#                temp = dict((k,v) for k,v in data.iteritems() if k in perm)
#                serial.dump(temp, f, -1)
#        except IOError: error("Failed to save pickled shared data")
        
#monitor requests and exit to save resources
any_changes = False
from settings import CONFIG_FLUSH_PERIOD
from threading import Timer

def check_changes():
    global any_changes
    if any_changes:
        debug("changes found, flush")
        any_changes = False #reset flag
        try:
            with sync: #block changes
                with open(SHARED_FILE_STORAGE, 'wb') as f:
                    serial.dump(data, f, -1)
        except IOError: error("Failed to save pickled shared data")
    
def flush_timeout():
    check_changes()
    newTimer(CONFIG_FLUSH_PERIOD) #restart timer
    
def newTimer(sec):
    global flush_timer
    flush_timer = Timer(sec, flush_timeout)
    flush_timer.start()
    
flush_timer = None
newTimer(CONFIG_FLUSH_PERIOD) #start monitor
        